package be.bonamis.umpire.business.umpire.impl;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import be.bonamis.projects.umpire.business.actions.GetAllQuizA;
import be.bonamis.projects.umpire.business.actions.GetAllQuizR;
import be.bonamis.projects.umpire.business.actions.GetClubsA;
import be.bonamis.projects.umpire.business.actions.GetClubsR;
import be.bonamis.projects.umpire.business.actions.GetFPReportA;
import be.bonamis.projects.umpire.business.actions.GetFPReportR;
import be.bonamis.projects.umpire.business.actions.GetGamesByUmpireA;
import be.bonamis.projects.umpire.business.actions.GetGamesByUmpireR;
import be.bonamis.projects.umpire.business.actions.GetLeagueDayA;
import be.bonamis.projects.umpire.business.actions.GetLeagueDayR;
import be.bonamis.projects.umpire.business.actions.GetLoginA;
import be.bonamis.projects.umpire.business.actions.GetLoginR;
import be.bonamis.projects.umpire.business.actions.GetMonthsA;
import be.bonamis.projects.umpire.business.actions.GetMonthsR;
import be.bonamis.projects.umpire.business.actions.GetQuizA;
import be.bonamis.projects.umpire.business.actions.GetQuizR;
import be.bonamis.projects.umpire.business.actions.GetQuizResultA;
import be.bonamis.projects.umpire.business.actions.GetQuizResultR;
import be.bonamis.projects.umpire.business.actions.GetQuizStatsA;
import be.bonamis.projects.umpire.business.actions.GetQuizStatsR;
import be.bonamis.projects.umpire.business.actions.GetUmpireByIdA;
import be.bonamis.projects.umpire.business.actions.GetUmpiresA;
import be.bonamis.projects.umpire.business.actions.GetUmpiresByLDA;
import be.bonamis.projects.umpire.business.actions.GetUmpiresR;
import be.bonamis.projects.umpire.business.dto.ClubDTO;
import be.bonamis.projects.umpire.business.dto.GameDTO;
import be.bonamis.projects.umpire.business.dto.IndividualResultDTO;
import be.bonamis.projects.umpire.business.dto.LeagueDayDTO;
import be.bonamis.projects.umpire.business.dto.QuizDTO;
import be.bonamis.projects.umpire.business.dto.QuizStatsDTO;
import be.bonamis.projects.umpire.business.dto.UmpireDTO;
import be.bonamis.umpire.business.UmpireService;
import be.bonamis.umpire.business.mapping.Mapper;
import be.bonamis.umpire.business.umpire.UmpireHandler;
import be.bonamis.umpire.domain.Club;
import be.bonamis.umpire.domain.LeagueDay;
import be.bonamis.umpire.domain.Umpire;
import be.bonamis.umpire.domain.history.FairPlayReport;
import be.bonamis.umpire.domain.history.Game;
import be.bonamis.umpire.domain.quiz.Quiz;
import be.bonamis.umpire.history.ClubFPScore;
import be.bonamis.umpire.quiz.IndividualResult;
import be.bonamis.umpire.quiz.QuizStat;

import com.google.common.io.BaseEncoding;

@Service
public class UmpireHandlerImpl implements UmpireHandler {

	@Autowired
	private UmpireService service;

	@Override
	public GetLoginR handleGetLoginA(GetLoginA<GetLoginR> action) {
		int size = service.getUmpiresList().size();
		if (size == 0) {
			service.mergeAll();
		}
		size = service.getUmpiresList().size();
		Umpire umpire = service
				.getUmpireByLoginAndPassword(action.getLogin(), action.getPassword());
		return new GetLoginR(umpireToUmpireDTO(umpire));
	}

	@Override
	public GetClubsR handleGetClubsA(GetClubsA<GetClubsR> action) {
		List<Club> clubsList = service.getClubsList();
		return new GetClubsR(clubsListToclubsDTO(clubsList));
	}

	@Override
	public GetUmpiresR handleGetUmpiresA(GetUmpiresA<GetUmpiresR> action) {
		List<Umpire> list = service.getUmpiresList();
		GetUmpiresR response = new GetUmpiresR();
		response.setUmpiresDTOList(umpireListToUmpireDTOList(list));
		return response;
	}

	@Override
	public GetMonthsR handleGetMonthsA(GetMonthsA<GetMonthsR> action) {
		Set<DateTime> set = service.getDispoMonthList();
		Set<Date> setDates = new TreeSet<Date>();

		for (DateTime dateTime : set) {
			setDates.add(dateTime.toDate());
		}
		GetMonthsR response = new GetMonthsR();
		response.setSetDates(setDates);
		return response;
	}

	@Override
	public GetLeagueDayR handleGetLeagueDayA(GetLeagueDayA<GetLeagueDayR> action) {
		List<LeagueDay> list = service.getLeagueDayListByUmpireByMonth(action.getUmpireId(),
				action.getMonth(), action.getYear());
		List<LeagueDayDTO> dto = new ArrayList<LeagueDayDTO>();
		for (LeagueDay leagueDay : list) {
			dto.add(leagueDayToDto(leagueDay));
		}
		GetLeagueDayR resp = new GetLeagueDayR();
		resp.setLeagueDayDtoList(dto);
		return resp;
	}

	@Override
	public GetUmpiresR handleGetUmpiresByLDA(GetUmpiresByLDA<GetUmpiresR> action) {
		List<Umpire> list = service.getUmpiresListByLeagueDay(action.getLeagueDayId());
		GetUmpiresR resp = new GetUmpiresR();
		resp.setUmpiresDTOList(umpireListToUmpireDTOList(list));
		return resp;
	}

	@Override
	public GetLoginR handleGetUmpireByIdA(GetUmpireByIdA<GetLoginR> action) {
		Umpire umpire = service.getUmpireById(action.getId());
		return new GetLoginR(umpireToUmpireDTO(umpire));
	}

	@Override
	public GetQuizR handleGetQuizA(GetQuizA<GetQuizR> action) {
		return new GetQuizR(Mapper.quizToQuizDTO(service.getQuiz(action.getId())));
	}

	@Override
	public GetAllQuizR handleGetAllQuizA(GetAllQuizA<GetAllQuizR> action) {
		List<QuizDTO> list = new ArrayList<QuizDTO>();
		List<Quiz> dates = service.getAllQuiz();
		for (Quiz quiz : dates) {
			list.add(Mapper.quizToQuizDTO(quiz));
		}
		return new GetAllQuizR(list);
	}

	@Override
	public GetGamesByUmpireR handleGetGamesByUmpireA(GetGamesByUmpireA<GetGamesByUmpireR> action) {
		GetGamesByUmpireR response = new GetGamesByUmpireR();
		List<GameDTO> games = new ArrayList<GameDTO>();
		List<Game> list = service.findGamesByUmpire((int) action.getId());
		for (Game game : list) {
			games.add(Mapper.gameToGameDTO(game));
		}
		response.setGames(games);
		return response;
	}

	@Override
	public GetFPReportR handleGetFPReportA(GetFPReportA<GetFPReportR> action) {
		GetFPReportR reportR = new GetFPReportR();
		FairPlayReport report01 = new FairPlayReport();
		report01.setAccueil(action.getHomePoints().get(0));
		report01.setComportementJoueurs(action.getHomePoints().get(1));
		report01.setLineUp((action.getHomePoints().get(2)));
		FairPlayReport report02 = new FairPlayReport();
		report02.setAccueil(action.getAwayPoints().get(0));
		report02.setComportementJoueurs(action.getAwayPoints().get(1));
		report02.setLineUp((action.getAwayPoints().get(2)));
		List<ClubFPScore> scores = service.putUmpireFPReport(action.getUmpireId(), action.getGameId(),
				report01, report02).getScores();
		reportR.setList(Mapper.scoresToScoresDTO(scores));

		return reportR;
	}

	@Override
	public GetQuizStatsR handleGetQuizStatsA(GetQuizStatsA<GetQuizStatsR> action) {
		QuizStat quizStat = service.createQuizStats(action.getId());
		QuizStatsDTO dto = Mapper.quizStatToDto(quizStat);
		return new GetQuizStatsR(dto);
	}

	@Override
	public GetQuizResultR handleGetQuizResultA(GetQuizResultA<GetQuizResultR> action) {
		IndividualResult result = null;
		if (action.getResponses() == null) {
			result = service.getResponsesFromUmpireFromQuiz(action.getPersonId(),
					action.getQuizId());
		} else {
			result = service.umpirePutResponsesOnQuiz(action.getPersonId(), action.getResponses(),
					action.getQuizId());
		}

		IndividualResultDTO mapperResult = Mapper.resultToDto(result);

		IndividualResultDTO dto = new IndividualResultDTO();
		dto.setResponses(mapperResult.getResponses());
		dto.setScore(mapperResult.getScore());
		dto.setStyles(mapperResult.getStyles());
		return new GetQuizResultR(dto);
	}

	private LeagueDayDTO leagueDayToDto(LeagueDay ld) {
		LeagueDayDTO dto = new LeagueDayDTO();
		dto.setBlocked(ld.isBlocked());
		dto.setDay(ld.getDay().toDate());
		dto.setGameType(ld.getType().getDescriptionFr());
		dto.setId(ld.getId());
		return dto;
	}

	private ClubDTO clubsListToclubsDTO(List<Club> clubsList) {
		ClubDTO dto = new ClubDTO();
		List<String> workList = new ArrayList<String>();
		for (Club club : clubsList) {
			workList.add(club.getName());
		}
		dto.setClubsList(workList);
		return dto;
	}

	private UmpireDTO umpireToUmpireDTO(Umpire umpire) {
		UmpireDTO dto = new UmpireDTO();
		SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
		if (umpire.getBirthDay() != null) {
			dto.setBirthDate(sdf.format(umpire.getBirthDay()));
		}
		dto.setCity(umpire.getAddress().getMunicipality());
		if (umpire.getClub() != null) {
			dto.setClub(umpire.getClub().getName());
		}
		dto.setEmail(umpire.getEmail());
		dto.setFirstName(umpire.getFirstName());
		dto.setGsm(umpire.getPhoneNumber());
		dto.setId(umpire.getId());
		dto.setLastName(umpire.getLastName());
		if (umpire.getRanking() != null) {
			dto.setRanking(umpire.getRanking().getName());
		}
		if (umpire.getPicture() != null) {
			byte[] imageByteArray = umpire.getPicture();
			String base64 = BaseEncoding.base64().encode(imageByteArray);
			base64 = "data:image/png;base64," + base64;
			dto.setImageData(base64);
		} else {
			dto.setImageData(null);
		}
		return dto;
	}

	private List<UmpireDTO> umpireListToUmpireDTOList(List<Umpire> list) {
		List<UmpireDTO> DTOlist = new ArrayList<UmpireDTO>();
		for (Umpire umpire : list) {
			DTOlist.add(umpireToUmpireDTO(umpire));
		}
		return DTOlist;
	}
}
